package sequence;

/**
 * @author hubert
 * @date 2018/11/13
 * @description ObjectIdConverter
 */
public class ObjectIdConverter {

	/**
	 * 将 64进制编码长度为16位的ID 转换为 16进制编码的长度为24位的ID
	 * @param shortId
	 * @return
	 */
	public static String unCompressObjectId(String shortId){
		if(shortId == null || shortId.length() != 16){
			throw new IllegalArgumentException();
		}

		StringBuilder res = new StringBuilder(24);
		char[] str = shortId.toCharArray();
		for(int i = 0; i < str.length; i += 2){
			int pre = char2Int(str[i]),end = char2Int(str[i+1]);
			res.append(int2Char( (pre >> 2) ));
			res.append(int2Char( ((pre & 3) << 2) + (end >> 4) ));
			res.append(int2Char( end & 15 ));
		}
		return res.toString();
	}

	/**
	 * 将 16进制编码的长度为24位的ID 转换为 64进制编码长度为16位的ID
	 * @param objectId
	 * @return
	 */
	public static String compressObjectId(String objectId){
		if(objectId == null || objectId.length() != 24){
			throw new IllegalArgumentException();
		}

		StringBuilder res = new StringBuilder(16);
		char[] str = objectId.toCharArray();
		for(int i = 0; i < str.length; i += 3){
			int pre = char2Int(str[i]),mid = char2Int(str[i+1]),end = char2Int(str[i+2]);
			res.append(int2Char( (pre << 2) + (mid >> 2) ));
			res.append(int2Char( ((mid & 3) << 4) + end ));
		}
		return res.toString();
	}

	/**
	 * 支持64进制bit转字符
	 * 0～9,a～z,A～Z,-,_
	 * @param i
	 */
	private static char int2Char(int i){
		if(i >= 0 && i <= 9){
			return (char) ('0'+i);
		}else if(i >= 10 && i <= 35){
			return (char) ('a'+i-10);
		}else if(i >= 36 && i <= 61){
			return (char) ('A'+i-36);
		}else if(i == 62){
			return '-';
		}else if(i == 63){
			return '_';
		}else{
			throw new IllegalArgumentException();
		}
	}

	/**
	 * 支持64进制字符转bit
	 * 0～9,a～z,A～Z,-,_
	 * @param c
	 */
	private static int char2Int(char c) {
		if (c >= '0' && c <= '9') {
			return c - '0';
		} else if (c >= 'a' && c <= 'z') {
			return 10 + c - 'a';
		} else if (c >= 'A' && c <= 'Z') {
			return 36 + c - 'A';
		} else if (c == '-') {
			return 62;
		} else if (c == '_') {
			return 63;
		} else {
			throw new IllegalArgumentException();
		}
	}

}
